﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Collections.Specialized;

namespace NETXPF.Library
{
    /// <summary>
    /// Provides straightforward utility functions for converting any arbitrary object to a JSON string.
    /// </summary>
    public static class JSON
    {
        public static object Parse(string json)
        {
            int idx = 0;
            bool success = true;
            object o = JSONParser.ParseValue(json.ToCharArray(), ref idx, ref success);
            if (!success)
            {
                throw new JSONParseException("Parse error at " + idx + "; string=" + json);
            }
            return o;
        }
        public static string JSONify(string s)
        {
            return s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r", "\\r").Replace("\n", "\\n").Replace("/", "\\/");
        }
        public static string JSONify(ValueType v)
        {
            return v.ToString();
        }
        public static string JSONify(IEnumerable e)
        {
            StringBuilder json = new StringBuilder();
            if (e is List<KeyValuePair<string, object>>)
            {
                List<KeyValuePair<string, object>> itemData = (List<KeyValuePair<string, object>>)e;
                json.Append("{");
                for (int i = 0; i < itemData.Count; i++)
                {
                    json.Append("\"");
                    json.Append(itemData[i].Key);
                    json.Append("\"");
                    json.Append(":");
                    json.Append(JSONify(itemData[i].Value));
                    if (i < itemData.Count - 1)
                    {
                        json.Append(",");
                    }
                }
                json.Append("}");
                return json.ToString();
            }
            else
            {
                json.Append("[");
                bool first = true;
                foreach (object item in e)
                {
                    if (!first)
                    {
                        json.Append(",");
                    }
                    json.Append(JSONify(item));
                    first = false;
                }
                json.Append("]");
                return json.ToString();
            }
        }
        /// <summary>
        /// Supports:
        /// ValueTypes (ToString())
        /// string
        /// Hashtable
        /// NameValueCollection
        /// any IEnumerable
        /// any object (public properties)
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public static string JSONify(object item)
        {
            StringBuilder json = new StringBuilder();
            if (item is ValueType)
            {
                json.Append(JSONify(item as ValueType));
                return json.ToString();
            }
            else if (item is string)
            {
                json.Append("\"");
                json.Append(JSONify(item as string));
                json.Append("\"");
                return json.ToString();
            }
            else if (item is Hashtable)
            {
                List<KeyValuePair<string, object>> data = new List<KeyValuePair<string, object>>();
                foreach (object key in ((Hashtable)item).Keys)
                {
                    data.Add(new KeyValuePair<string, object>(key.ToString(), ((Hashtable)item)[key]));
                }
                return JSON.JSONify(data);
            }
            else if (item is NameValueCollection)
            {
                List<KeyValuePair<string, object>> data = new List<KeyValuePair<string, object>>();
                foreach (string key in ((NameValueCollection)item).AllKeys)
                {
                    data.Add(new KeyValuePair<string, object>(key, ((NameValueCollection)item)[key]));
                }
                return JSON.JSONify(data);
            }
            else if (item is IEnumerable)
            {
                json.Append(JSONify(item as IEnumerable));
                return json.ToString();
            }
            List<KeyValuePair<string, object>> objectData = new List<KeyValuePair<string, object>>();
            System.Reflection.PropertyInfo[] props = item.GetType().GetProperties();
            for (int i = 0; i < props.Length; i++)
            {
                objectData.Add(new KeyValuePair<string, object>(props[i].Name, props[i].GetValue(item, null)));
            }
            return JSON.JSONify(objectData);
        }
    }
}
